package com.zimin.cloud.gateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * @Author: 嘉阳
 * @Date: 2021/1/17
 * @Describe: 请求 拦截器
 */
@Component
public class RequestGlobalFilter implements GlobalFilter, Ordered {

    /*
      该拦截器针对POST请求 目前WEBFLUX无法读取body参数 即定义该拦截器 重写body参数
      示例：https://www.cnblogs.com/grimm/p/14032710.html
     */

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        var method = exchange.getRequest().getMethod();
        if (method == null || method.matches(HttpMethod.GET.name()) || method.matches(HttpMethod.DELETE.name())) {
            return chain.filter(exchange);
        }
        return DataBufferUtils.join(exchange.getRequest().getBody()).map(dataBuffer -> {
            var bytes = new byte[dataBuffer.readableByteCount()];
            dataBuffer.read(bytes);
            DataBufferUtils.release(dataBuffer);
            return bytes;
        }).defaultIfEmpty(new byte[0]).flatMap(bytes -> {
            var dataBufferFactory = exchange.getResponse().bufferFactory();
            var decorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
                @Override
                public Flux<DataBuffer> getBody() {
                    if (bytes.length > 0) {
                        return Flux.just(dataBufferFactory.wrap(bytes));
                    }
                    return Flux.empty();
                }
            };
            return chain.filter(exchange.mutate().request(decorator).build());
        });
    }

    @Override
    public int getOrder() {
        return -199;
    }

}
